<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>手写call_apply_bind(实现原理)</title>
	</head>
	<body>

	</body>
	<script type="text/javascript">
		一、 call：
		使用一个指定的 this 值和一个或多个参数来调用一个函数。
		实现要点：
		1. this 可能传入 null；
		2. 传入不固定个数的参数；
		3. 函数可能有返回值；
		Function.prototype.myCall=function(context) {
			var context = context || window;
			context.fn = this;
			var args = [];
			for (var i = 0; i < arguments.length, i++) {
				args.push('arguments[' + i + ']')
			}
			var result = eval('context.fn(' + args + ')');
			delete context.fn;
			return result
		}



		二、 apply：
		apply 和 call 一样， 唯一的区别就是 call 是传入不固定个数的参数， 而 apply 是传入一个数组。
		实现要点：
		1、 this 可能传入 null；
		2、 传入一个数组；
		3、 函数可能有返回值；
		Function.prototype.myApply = function(context, arr) {
			var context = context || window;
			context.fn = this;
			var result;
			if (!arr) {
				result = context.fn();
			} else {
				var args = [];
				for (var i = 0, len = arr.length; i < len; i++) {
					args.push('arr[' + i + ']');
				}
				result = eval('context.fn(' + args + ')')
			}
			delete context.fn
			return result;
		}


		三、 bind：
		bind 方法会创建一个新的函数， 在 bind() 被调用时， 这个新函数的 this 被指定为 bind() 的第一个参数， 而其余参数将作为新函数的参数， 供调用时使用。
		实现要点：
		1、 bind() 除了 this 外， 还可传入多个参数；
		2、 bing 创建的新函数可能传入多个参数；
		3、 新函数可能被当做构造函数调用；
		4、 函数可能有返回值；
		Function.prototype.myBind = function(context) {
			var self = this;
			var args = Array.prototype.slice.call(arguments, 1);
			var fNOP = function() {};
			var fBound = function() {
				var bindArgs = Array.prototype.slice.call(arguments);
				return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
			}
			fNOP.prototype = this.prototype;
			fBound.prototype = new fNOP();
			return fBound;
		}
	</script>
</html>
